﻿namespace Admin.NET.Core;

/// <summary>
/// 数据连接服务
/// </summary>
[ApiDescriptionSettings(Order = 249)]
public class SysDbLinkService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<SysDbLink> _sysDbLinkRep;

    private readonly DataBaseManager _dataBaseManager;

    private readonly SysDictDataService _sysDictDataService;

    public SysDbLinkService(SqlSugarRepository<SysDbLink> sysDbLinkRep,
        DataBaseManager dataBaseManager,
        SysDictDataService sysDictDataService)
    {
        _sysDbLinkRep = sysDbLinkRep;
        _dataBaseManager = dataBaseManager;
        _sysDictDataService = sysDictDataService;
    }

    /// <summary>
    /// 分页查询数据连接
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Page")]
    [DisplayName("分页查询数据连接")]
    public async Task<SqlSugarPagedList<DbLinkOutput>> Page(PageSysDbLinkInput input)
    {
        input.SearchKey = input.SearchKey?.Trim();
        var query = _sysDbLinkRep.AsQueryable()
            .WhereIF(!string.IsNullOrEmpty(input.SearchKey), u =>
                u.Name.Contains(input.SearchKey)
                || u.DBType.Contains(input.SearchKey)
                || u.Host.Contains(input.SearchKey)
                || u.UserName.Contains(input.SearchKey)
                || u.Password.Contains(input.SearchKey)
                || u.ServiceName.Contains(input.SearchKey)
                || u.Remark.Contains(input.SearchKey)
                || u.DBSchema.Contains(input.SearchKey)
                || u.TableSpace.Contains(input.SearchKey)
                || u.OracleParam.Contains(input.SearchKey)
            )
            .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.DBType), u => u.DBType.Contains(input.DBType.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Host), u => u.Host.Contains(input.Host.Trim()))
            .WhereIF(input.Port > 0, u => u.Port == input.Port)
            .WhereIF(!string.IsNullOrWhiteSpace(input.UserName), u => u.UserName.Contains(input.UserName.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Password), u => u.Password.Contains(input.Password.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.ServiceName), u => u.ServiceName.Contains(input.ServiceName.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Remark), u => u.Remark.Contains(input.Remark.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.DBSchema), u => u.DBSchema.Contains(input.DBSchema.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.TableSpace), u => u.TableSpace.Contains(input.TableSpace.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.OracleParam), u => u.OracleParam.Contains(input.OracleParam.Trim()))
            .WhereIF(input.OracleExtend > 0, u => u.OracleExtend == input.OracleExtend)
            .Select<DbLinkOutput>();
        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
    }

    /// <summary>
    /// 增加数据连接
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Add")]
    [DisplayName("增加数据连接")]
    public async Task<long> Add(AddSysDbLinkInput input)
    {
        var entity = input.Adapt<SysDbLink>();
        await _sysDbLinkRep.InsertAsync(entity);
        return entity.Id;
    }

    /// <summary>
    /// 删除数据连接
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Delete")]
    [DisplayName("删除数据连接")]
    public async Task Delete(DeleteSysDbLinkInput input)
    {
        var entity = await _sysDbLinkRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        //await _sysDbLinkRep.FakeDeleteAsync(entity);   //假删除
        await _sysDbLinkRep.DeleteAsync(entity);   //真删除
    }

    /// <summary>
    /// 更新数据连接
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Update")]
    [DisplayName("更新数据连接")]
    public async Task Update(UpdateSysDbLinkInput input)
    {
        var entity = input.Adapt<SysDbLink>();
        await _sysDbLinkRep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
    }

    /// <summary>
    /// 获取数据连接
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "Detail")]
    [DisplayName("获取数据连接")]
    public async Task<SysDbLink> Detail([FromQuery] QueryByIdSysDbLinkInput input)
    {
        return await _sysDbLinkRep.GetFirstAsync(u => u.Id == input.Id);
    }

    /// <summary>
    /// 获取数据连接列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "List")]
    [DisplayName("获取数据连接列表")]
    public async Task<List<DbLinkOutput>> List([FromQuery] PageSysDbLinkInput input)
    {
        return await _sysDbLinkRep.Context.Queryable<SysDbLink, SysDictData, SysDictType>(
            (a, b, c) => new JoinQueryInfos(
                JoinType.Left, a.DBType == b.Code,
                JoinType.Left, b.DictTypeId == c.Id && c.Code == "dbType"))
                .OrderBy((a, b, c) => a.CreateTime, OrderByType.Desc).
                Select((a, b, c) => new DbLinkOutput()
                {
                    Id = a.Id,
                    parentId = b.Id == null ? -1 : b.Id,
                    CreateTime = a.CreateTime,
                    CreateUserId = a.CreateUserId,
                    CreateUserName = a.CreateUserName,
                    DBType = a.DBType,
                    Name = a.Name,
                    Host = a.Host,
                    UpdateTime = a.UpdateTime,
                    UpdateUserId = a.UpdateUserId,
                    UpdateUserName = a.UpdateUserName,
                    Port = a.Port,
                }).Distinct().ToListAsync();
        //return await _sysDbLinkRep.AsQueryable().Select<DbLinkOutput>().ToListAsync();
    }

    /// <summary>
    /// 测试连接.
    /// </summary>
    /// <param name="input">实体对象.</param>
    [HttpPost("Test")]
    [ApiDescriptionSettings(Name = "Test")]
    [DisplayName("测试连接")]
    public void TestDbConnection([FromBody] DbLinkTestInput input)
    {
        var entity = input.Adapt<SysDbLink>();
        entity.OracleParam = new OracleParamModel()
        {
            oracleExtend = input.OracleExtend.ToBoolean(),
            oracleRole = input.oracleRole,
            oracleLinkType = input.oracleLinkType,
            oracleService = input.oracleService
        }.ToJson();

        if (!_dataBaseManager.IsConnection(entity))
            throw Oops.Oh(ErrorCodeEnum.D1507);
    }

    /// <summary>
    /// 下拉框列表.
    /// </summary>
    /// <returns></returns>
    [HttpGet("Selector")]
    [ApiDescriptionSettings(Name = "Selector")]
    [DisplayName("下拉框列表")]
    public async Task<dynamic> GetSelector([FromQuery] string type)
    {
        var data = (await List(new PageSysDbLinkInput())).Adapt<List<DbLinkSelectorOutput>>();

        // 数据库分类
        var dbTypeList = await _sysDictDataService.GetDataList("dbType");
        var output = new List<DbLinkSelectorOutput>();
        if (type.IsNullOrEmpty())
        {
            output.Add(new DbLinkSelectorOutput()
            {
                id = "-2",
                parentId = "0",
                name = "",
                num = data.FindAll(x => x.parentId == null).Count
            });
            // 获取选项
            var dbOptions = App.GetOptions<DbConnectionOptions>().ConnectionConfigs.FirstOrDefault();
            var defaultDBType = dbOptions.DbType.ToString();
            if (defaultDBType.Equals("Kdbndp"))
            {
                defaultDBType = "KingbaseES";
            }
            if (defaultDBType.Equals("Dm"))
            {
                defaultDBType = "DM";
            }
            output.Add(new DbLinkSelectorOutput()
            {
                id = "0",
                parentId = "-2",
                name = "默认数据库",
                dbType = defaultDBType,
                num = 1
            });
        }

        output.Add(new DbLinkSelectorOutput()
        {
            id = "-1",
            parentId = "0",
            name = "未分类",
            num = data.FindAll(x => x.parentId == null).Count
        });

        foreach (var item in dbTypeList)
        {
            var index = data.FindAll(x => x.dbType.Equals(item.Code)).Count;
            if (index > 0)
            {
                output.Add(new DbLinkSelectorOutput()
                {
                    id = item.Id.ToString(),
                    name = item.Name
                });
            }
        }

        return new { list = output.Union(data).ToList().ToTree() };
    }

    /// <summary>
    /// 信息.
    /// </summary>
    /// <param name="id">主键值.</param>
    /// <returns></returns>
    [NonAction]
    public async Task<SysDbLink> GetInfo(long id)
    {
        return await _sysDbLinkRep.GetFirstAsync(u => u.Id == id);
    }
}